<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .snake {
            width: 1200px;
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: auto;
        }

        .map {
            width: 1200px;
            height: 600px;
            background-color: rgb(190, 177, 153);
            position: absolute;
        }

        .body div {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background-color: #000;
            position: absolute;
            color: red;
            top: 30px;
            left: 30px;
            text-align: center;
            line-height: 30px;
        }

        .food {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background-color: green;
            position: absolute;
        }
    </style>
</head>

<body>
    
    <div class="snake">
        <h1 class="score">0</h1>
        <button disabled >重新开始</button>
        <div class="map">
            <div class="body"></div>
            <div class="food"></div>
        </div>
    </div>

    <script>

        // 初始化的身体

        // 初始化的食物  --- 位置

        // 键盘事件
        //     判断位置
        //         是否到达边界
        //         是否吃到食物   --- 身体变长了 ， 分数 ，重新生成食物(改变食物的位置)



        // “地图”  
        //    蛇的位置在每一个格子中间
        //    食物也必须在格子中

        // 假定食物和蛇的大小都是20
        //    蛇移动的速度是20   
        //    食物的位置也必须是20的倍数

        const rand = (min , max) => parseInt(Math.random() * (max - min) + min)

        const getCss = (ele, prop) => parseInt(getComputedStyle(ele)[prop]);


        const setCss = (ele, options) => {
            for (let prop in options) {
                // ele.style.left = '100px'
                ele.style[prop] = options[prop];
            }
        }


        function Snake(ele , time) {
            this.oBox = document.querySelector(ele) ;
            this.oScore = this.oBox.querySelector('.score') ;
            this.food = this.oBox.querySelector('.food') ;
            this.oBodyBox = this.oBox.querySelector('.body') ;
            this.oMap = this.oBox.querySelector('.map');
            this.score = 0 ;

            this.oRestart = this.oBox.querySelector('button') ;

            this.speed = 30 ;

            this.time = time || 300 ;

            this.t = null ;

            // 初始化创建身体
            this.createBody() ;

            // 获取身体
            this.oBodies = this.oBodyBox.querySelectorAll('div') ;

            // 创建食物  --- 随机食物的位置
            this.createFood() ;


            // 移动事件
            this.event() ;

            // 
            this.restart() ;
        }

        // 初始化创建身体
        Snake.prototype.createBody = function() {
            // 默认身体有10节
            // 创建10个标签  插入到bodyBox中去


            // for(let i = 0 ; i < 10 ; i++) {
            //     const oDiv = document.createElement('div') ;
            //     // 给蛇的身体加了数字   无所谓
            //     oDiv.innerHTML = i ;
            //     this.oBodyBox.appendChild(oDiv) ;
            // }

            // 文档碎片  减少页面的回流   先把所有的标签存入文档碎片   创建完毕之后一次性插入页面
            const fragment = document.createDocumentFragment() ;
            for(let i = 0 ; i < 10 ; i++) {
                const oDiv = document.createElement('div') ;
                // 给蛇的身体加了数字   无所谓
                oDiv.innerHTML = i ;
                fragment.appendChild(oDiv) ;
            }
            this.oBodyBox.appendChild(fragment);
        }

        // 创建食物  --- 随机食物的位置
        Snake.prototype.createFood = function() {
            // 食物的位置必须是speed的倍数
            let maxX = this.oMap.clientWidth / this.speed;
            let maxY = this.oMap.clientHeight / this.speed;

            let x = rand(0,maxX) * this.speed ;
            let y = rand(0 , maxY) * this.speed ;


            setCss(this.food , {
                left : x + 'px' ,
                top : y + 'px'
            })
        }


        Snake.prototype.event = function() {
            document.onkeydown = e => {
                clearInterval(this.t);
                const k = e.keyCode ;
                // 先获取蛇的当前位置   通过蛇的头
                let x = getCss(this.oBodies[0] , 'left') ;
                let y = getCss(this.oBodies[0] , 'top') ;

                let maxX = this.oMap.clientWidth - this.speed ;
                let maxY = this.oMap.clientHeight - this.speed ;

              
                this.t = setInterval(() => {

                    // 判断是否到达边界
                    if(x <= 0 || x >= maxX || y <= 0 || y >= maxY) {
                        alert('game over');
                        clearInterval(this.t);

                        // 把分数存入localStorage  判断是否刷新记录
                        let res = localStorage.getItem('score') ;
                        if(res) {
                            if(this.score > res) {
                                alert('你又刷新了自己的记录')
                                localStorage.setItem('score' , this.score);
                            } else {
                                alert('没有突破自己,加油哦')
                            }
                        } else {
                            localStorage.setItem('score' , this.score);
                        }
                       
                        // 重新开始
                        this.oRestart.disabled = false ;
                        return
                    }

                    if(k === 40) y += this.speed ;
                    if(k === 38) y -= this.speed ;
                    if(k === 39) x += this.speed ;
                    if(k === 37) x -= this.speed ;


                    // 设置头的位置
                    setCss(this.oBodies[0] , {
                        left : x + 'px' ,
                        top : y + 'px'
                    })


                    for(let i = this.oBodies.length - 1 ; i > 0 ; i--) {
                        setCss(this.oBodies[i] , {
                            left : getCss(this.oBodies[i-1] , 'left') + 'px' ,
                            top : getCss(this.oBodies[i-1] , 'top') + 'px' ,
                        })
                    }

                    // 判断是否吃到食物
                    if(getCss(this.oBodies[0], 'left') === getCss(this.food , 'left') && getCss(this.oBodies[0], 'top') === getCss(this.food , 'top')) {
                        console.log('吃到了');
                        // 分数变化
                        this.score++ ;
                        this.oScore.innerHTML = this.score;

                        // 身体变长
                        this.addBody() ;
                        // 重新生成位置
                        this.createFood();
                    }

                } , this.time)
            }
        }



        Snake.prototype.addBody = function() {
            // 创建一个div
            const oDiv = document.createElement('div') ;
            oDiv.innerHTML = this.oBodies.length ;
            // 设置位置
            setCss(oDiv , {
                left : getCss(this.oBodies[this.oBodies.length - 1] , 'left') + 'px' ,
                top : getCss(this.oBodies[this.oBodies.length - 1] , 'top') + 'px' ,
            })
            this.oBodyBox.appendChild(oDiv) ;
            this.oBodies = this.oBodyBox.querySelectorAll('div');
        }



        Snake.prototype.restart = function() {
            this.oRestart.onclick = () => {
                this.oScore.innerHTML = 0 ;
                this.oBodyBox.innerHTML = '';
                new Snake('.snake');
            }
        }

        new Snake('.snake');






        
                    

    </script>

</body>

</html>